<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>函数防抖</title>
	</head>
	<body>
		<div style="height:2000px">
			<p>防抖动：将几次操作合并为一此操作进行。原理是维护一个计时器，规定在delay时间后触发函数，但是在delay时间内再次触发的话，就会取消之前的计时器而重新设置。这样一来，只有最后一次操作能被触发</p>
			<p>
				函数防抖的要点，也是需要一个setTimeout来辅助实现。延迟执行需要跑的代码。
			 如果方法多次触发，则把上次记录的延迟执行代码用clearTimeout清掉，重新开始。
			 如果计时完毕，没有方法进来访问触发，则执行代码。
			</p>
			<p>
				1. 首先，我们为scroll事件绑定处理函数，这时debounce函数会立即调用， 
				　  因此给scroll事件绑定的函数实际上是debounce内部返回的函数

				2. 每一次事件被触发，都会清除当前的 timer 然后重新设置超时调用。 
					 这就会导致每一次高频事件都会取消前一次的超时调用，导致事件处理程序不能被触发

				3. 只有当高频事件停止，最后一次事件触发的超时调用才能在delay时间后执行
				
				函数防抖的实现重点，就是巧用setTimeout做缓存池，而且可以轻易地清除待执行的代码。其实，用队列的方式也可以做到这种效果
			</p>
			
			<p id="show"></p>
			<input type="text" id="test">
		</div>
		
		<script>
			/* let test = document.getElementById("test"),
					show=document.getElementById("show"),
					count = 0;
			let timer = null;
			
			if(document.all){
				test.onpropertychange = function(){
					
					clearTimeout(timer); // 清除未执行的代码，重置回初始化状态
					
					timer = setTimeout(function(){
						count = count + 1;
						show.innerHTML = count;
					}, 500);
					
				}
			}
			else{
				test.oninput = function(){
					
					clearTimeout(timer);
					
					timer = setTimeout(function(){
						count = count + 1;
						show.innerHTML = count;
					}, 500);
					
				}
			} */
		</script>
		<script>
			let test = document.getElementById("test"),
					show=document.getElementById("show"),
					count = 0;
			
			if(document.all){
				test.onpropertychange = debounce(function(){
					count = count + 1;
					show.innerHTML = count;
				}, 500)
			}
			else{
				test.oninput = debounce(function(){
					count = count + 1;
					show.innerHTML = count;
				}, 500)
			}
			

			/** 封装函数防抖 **/
			function debounce(fun, delay){
				let timer = null;
				
				return function(){
					// 通过 ‘this’ 和 ‘arguments’ 获取函数的作用域和变量
					let that = this,
							args = arguments;
					
					clearTimeout(timer);
					timer = setTimeout(function(){
						fun.apply(that, args);
					}, delay);
				}
			}
			
		</script>
	</body>
</html>
